package com.tianji.learning.controller.service.impl;

import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.controller.service.IInteractionReplyService;
import com.tianji.learning.domain.dto.ReplyDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.ReplyPageQuery;
import com.tianji.learning.domain.vo.ReplyVO;
import com.tianji.learning.enums.QuestionStatus;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动问题的回答或评论 服务实现类
 * </p>
 *
 * @author zt
 * @since 2024-09-13
 */
@Service
@RequiredArgsConstructor
public class InteractionReplyServiceImpl extends ServiceImpl<InteractionReplyMapper, InteractionReply> implements IInteractionReplyService {

    private final UserClient userClient;
    private final InteractionQuestionMapper questionMapper;
    @Override
    public PageDTO<ReplyVO> queryReplyPage(ReplyPageQuery query) {
        //1.校验参数
        Long question = query.getQuestionId();
        Long answer = query.getAnswerId();
        if(question==null && answer==null){
            throw new BadRequestException("问题和回答不能都为空");
        }
        //2.查询回答
        Page<InteractionReply> page = this.lambdaQuery()
                .eq(question != null, InteractionReply::getQuestionId, question)
                .eq(InteractionReply::getAnswerId, answer==null?0L:answer)//三目运算符，表中默认answer_id为0
                .eq(InteractionReply::getHidden,false)
                .page(query.toMpPage(//先根据点赞数量排序，后根据创建时间排序
                        new OrderItem("liked_times",false),
                        new OrderItem("create_time",true)
                ));
        List<InteractionReply> records = page.getRecords();
        if(CollUtils.isEmpty(records)){
            return PageDTO.empty(0L,0L);
        }
        //3.补全其他数据
        Set<Long> userIds = new HashSet<>();
        Set<Long> targetReplyIds = new HashSet<>();
        for (InteractionReply record : records) {
            if(!record.getAnonymity()){
                userIds.add(record.getUserId());
                userIds.add(record.getTargetUserId());
            }
            if(record.getTargetReplyId()!=null&&record.getTargetReplyId()>0){
                targetReplyIds.add(record.getTargetReplyId());
            }
        }
        //查询目标回复，如果目标回复不是匿名，则需要查询出目标回复对象的用户信息
        if(targetReplyIds.size()>0){
            List<InteractionReply> replies = this.listByIds(targetReplyIds);
            Set<Long> targetUserIds = replies.stream()
                    .filter(Predicate.not(InteractionReply::getAnonymity))
                    .map(InteractionReply::getUserId)
                    .collect(Collectors.toSet());
            userIds.addAll(targetUserIds);
        }
        List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
        Map<Long,UserDTO> userDTOMap = new HashMap<>(userDTOS.size());
        if(CollUtils.isNotEmpty(userDTOS)){
            userDTOMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId,u->u));
        }
        //封装vo返回
        List<ReplyVO> voList = new ArrayList<>();
        for (InteractionReply record : records) {
            ReplyVO vo = BeanUtils.copyBean(record,ReplyVO.class);
            if(!record.getAnonymity()){
                UserDTO userDTO = userDTOMap.get(record.getUserId());
                if(userDTO!=null){
                    vo.setUserName(userDTO.getName());
                    vo.setUserIcon(userDTO.getIcon());
                    vo.setUserType(userDTO.getType());
                }
            }
            UserDTO targetUserDTO = userDTOMap.get(record.getTargetUserId());
            if(targetUserDTO!=null){
                vo.setTargetUserName(targetUserDTO.getName());
            }
            voList.add(vo);
        }
        return PageDTO.of(page,voList);
    }

    @Override
    public void addReply(ReplyDTO replyDTO) {
        //1.获取用户id
        Long userId = UserContext.getUser();
        //2.写入数据库
        InteractionReply reply = BeanUtils.copyBean(replyDTO, InteractionReply.class);
        reply.setUserId(userId);
        this.save(reply);
        //3.判断是否是回答
        InteractionQuestion question = questionMapper.selectById(reply.getQuestionId());
        if(replyDTO.getAnswerId()==null){
            //是回答
            question.setId(replyDTO.getQuestionId());
            question.setLatestAnswerId(reply.getId());
            question.setAnswerTimes(question.getAnswerTimes()+1);
        }else{
            //是评论
            InteractionReply answer = this.getById(reply.getAnswerId());
            answer.setReplyTimes(answer.getReplyTimes()+1);
            this.updateById(answer);
        }
        //4.是否是学生提交，是则将状态设置为未查看
        if(replyDTO.getIsStudent()){
            //说明是学生提交
            question.setStatus(QuestionStatus.UN_CHECK);
        }
        questionMapper.updateById(question);
    }

    @Override
    public PageDTO<ReplyVO> queryReplyPageAdmin(ReplyPageQuery query) {
        //1.校验
        Long question = query.getQuestionId();
        Long answer = query.getAnswerId();
        if(question==null&&answer==null){
            throw new BadRequestException("回答和评论id不能都为空");
        }
        //2.条件查询
        Page<InteractionReply> page = this.lambdaQuery()
                .eq(question != null, InteractionReply::getQuestionId, question)
                .eq(InteractionReply::getAnswerId, answer != null ? answer : 0L)
                .page(query.toMpPage(
                        new OrderItem("liked_times", false),
                        new OrderItem("create_time", true)
                ));
        List<InteractionReply> records = page.getRecords();
        if(records==null){
            return PageDTO.empty(0L,0L);
        }
        //3.补全数据
        Set<Long> userIds = new HashSet<>();
        for (InteractionReply record : records) {
            if(record.getUserId()!=null){
                userIds.add(record.getUserId());
            }
            if(record.getTargetUserId()!=null&&record.getTargetUserId()>0){
                userIds.add(record.getTargetUserId());
            }
        }
        //转成Map
        Map<Long,UserDTO> userDTOMap = new HashMap<>(userIds.size());
        List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
        if(CollUtils.isNotEmpty(userDTOS)){
            userDTOMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId,u->u));
        }
        //4.返回数据
        List<ReplyVO> voList = new ArrayList<>();
        for (InteractionReply record : records) {
            ReplyVO vo = BeanUtils.copyBean(record, ReplyVO.class);
            if(record.getUserId()!=null){
                UserDTO userDTO = userDTOMap.get(record.getUserId());
                vo.setUserName(userDTO.getName());
                vo.setUserIcon(userDTO.getIcon());
                vo.setUserType(userDTO.getType());
            }
            if(record.getTargetReplyId()!=null){
                UserDTO userDTO = userDTOMap.get(record.getTargetUserId());
                vo.setTargetUserName(userDTO.getName());
            }
            voList.add(vo);
        }
        return PageDTO.of(page,voList);
    }

    @Override
    public void hiddenReplyAdmin(Long id, Boolean hidden) {
        //1.校验
        if(id==null){
            throw new BadRequestException("参数错误");
        }
        //2.查询数据库
        InteractionReply reply = this.getById(id);
        if(reply==null){
            return;
        }
        //3.判断是回答还是评论
        if(reply.getAnswerId()==null){
            //是回答 则其下面的评论也要被隐藏起来
            List<InteractionReply> list = this.lambdaQuery()
                    .eq(InteractionReply::getAnswerId, reply.getId())
                    .list();
            for (InteractionReply l : list) {
                l.setHidden(hidden);
            }
            this.updateBatchById(list);
        }
        //4.更新数据库
        reply.setHidden(hidden);
        this.updateById(reply);
    }
}
